<?php


namespace Wxpay;

//商户分账类
use app\common\model\PayLog;
use think\facade\App;

class WxProfitsharing
{
    private $config = [
        "appid" => "wx1b5c6a97e8b6fbbc",  // 开放平台或商户平台APPID
        "mch_id" => "1558600161",  // 商户平台 商户号
        "key" => "bfca556b7dae3634d481553b2b709efd",  // 商户平台 秘钥KEY
        "TOKEN" => "1111111111",  // 此参数非必传 有的前端在jsapi 支付时会要求返回signature 参数  此参数即为此准备
    ];

    /**
     * 添加分账接收方
     * @param array $name 微信用户名
     */
    public function addreceiver($receiver=[])
    {
        $ret = [ 'code' => -1, 'msg' => "参数错误"];
        if (count($receiver)>0) {
            #组合需要用到的数据
            $receiver = json_encode($receiver, JSON_UNESCAPED_UNICODE);
            $data = [
                'mch_id' => $this->config['mch_id'],//商户号
                'appid' => $this->config['appid'],
                'nonce_str' => $this->getNonceStr(8),//随机串
                'sign_type' => 'HMAC-SHA256',
                'receiver' => $receiver
            ];
            $sign = $this->makeSign($data);
            $data['sign'] = $sign;
            #转换成xml
            $xml = $this->toXml($data);
            $url = 'https://api.mch.weixin.qq.com/pay/profitsharingaddreceiver';  //接收xml数据的文件
            $header[] = "Content-type: text/xml";
            $header[]="Accept-Charset:UTF-8";
            //定义content-type为xml,注意是数组
            $result = $this->postApi($xml, $url, $header);
            #显示错误信息
            if ($result['return_code'] == 'FAIL') {
                $ret['msg'] = $result['return_msg'];
            }
            if ($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS') {
                $ret['msg'] = $result['return_code'];
                $ret['code'] = 2;
                $ret['receiver'] = $result['receiver'];//分账接收方对象
            }
        }
        return $ret;
    }

    /**
     * 单次请求分账
     * @param $transaction_id 支付订单号
     * @param $out_order_no 分账单号
     * @param array $receivers 分账接收方
     * @return array
     */
    public function profitsharing($transaction_id,$out_order_no,$receivers=[])
    {
        $ret = ['code' => -1, 'msg' => "参数错误"];
        if (count($receivers)>0) {
            $receivers = json_encode($receivers, JSON_UNESCAPED_UNICODE);
            $data = [
                'mch_id' => $this->config['mch_id'],//商户号
                'appid' => $this->config['appid'],
                'nonce_str' => $this->getNonceStr(16),//随机串
                'sign_type' => 'HMAC-SHA256',
                'transaction_id' =>$transaction_id,
                'out_order_no' =>$out_order_no,
                'receivers' => $receivers
        ];
            $sign = $this->makeSign($data);
            $data['sign'] = $sign;
            #转换成xmll
            $xml = $this->toXml($data);
            $url = 'https://api.mch.weixin.qq.com/secapi/pay/profitsharing';
            $header[] = "Content-type: text/xml";      //定义content-type为xml,注意是数组
            $header[]="Accept-Charset:UTF-8";
            $result = $this->postApi($xml, $url, $header,true);
            #显示错误信息
            if ($result['return_code'] == 'FAIL') {
                $ret['msg'] = $result['return_msg'];
            }
            if($result['return_code']=='SUCCESS'&&$result['result_code']=='FAIL'){
                $ret['msg']=$result['err_code_des'];
            }
            if ($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS') {
                $ret['msg'] = $result['result_code'];//微信支付订单号
                $ret['code'] = 2;
                $ret['transaction_id']=$result['transaction_id'];//微信支付订单号
                $ret['out_order_no'] = $result['out_order_no'];//系统分账款单号
                $ret['order_id'] = $result['order_id'];//微信返回的分账单号
            }
        }
        return $ret;

    }


    /**
     * 删除分账接收方
     * @param $openid
     *
     */
    public function removereceiver($receiver)
    {
        $ret = ['code' => -1, 'msg' => "参数错误"];
        $receiver = json_encode($receiver, JSON_UNESCAPED_UNICODE);
        $data = [
            'mch_id' => $this->config['mch_id'],//商户号
            'appid' => $this->config['appid'],
            'nonce_str' => $this->getNonceStr(8),//随机串
            'sign_type' => 'HMAC-SHA256',
            'receiver' => $receiver
        ];
        $sign = $this->makeSign($data);
        $data['sign'] = $sign;
        #转换成xml
        $xml = $this->toXml($data);
        $url = 'https://api.mch.weixin.qq.com/pay/profitsharingremovereceiver';  //接收xml数据的文件
        $header[] = "Content-type: text/xml; charset=UTF-8";      //定义content-type为xml,注意是数组
        $result = $this->postApi($xml, $url, $header);
        #显示错误信息
        if ($result['return_code'] == 'FAIL') {
            $ret['msg'] = $result['return_msg'];
        }
        if($result['return_code']=='SUCCESS'&&$result['result_code']=='FAIL'){
            $ret['msg']=$result['err_code_des'];
        }
        if ($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS') {
            $ret['msg'] = $result['return_code'];
            $ret['code'] = 2;
            $ret['receiver'] = $result['receiver'];//分账接收方对象
        }
        return $ret;
    }


    /**
     * POST 请求
     * @param $xml
     * @param $url
     * @param $header
     * @return array
     */
    function postApi($xml, $url, $header,$isCa=false)
    {
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 兼容本地没有指定curl.cainfo路径的错误
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
        if ($isCa){
            curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
            curl_setopt($ch,CURLOPT_SSLCERT,App::getRootPath().'extend/Wxpay/cert/apiclient_cert.pem');
            //默认格式为PEM，可以注释
            curl_setopt($ch,CURLOPT_SSLKEY,App::getRootPath().'extend/Wxpay/cert/apiclient_key.pem');
        }
        $response = curl_exec($ch);
        if (curl_errno($ch)) {
            # 显示报错信息；终止继续执行
            die(curl_error($ch));
        }
        curl_close($ch);
        #转换成数组
        $result = $this->toArray($response);
        return $result;
    }


    /**
     * 生成签名
     * @return 签名，本函数不覆盖sign成员变量，如要设置签名需要调用SetSign方法赋值
     */
    private function makeSign($data)
    {
        # 去空
        $data = array_filter($data);
        #签名步骤一：按字典序排序参数
        ksort($data);
        #将数组转成url形式
        $string_a = http_build_query($data);
        $string_a = urldecode($string_a);
        #签名步骤二：在string后加入KEY
        $string_sign_temp = $string_a . "&key=" . $this->config['key'];
        #签名步骤三：
        //$sign=MD5($string_sign_temp);//MD5
        $sign = hash_hmac("sha256", $string_sign_temp, $this->config['key']);//HMAC-SHA256签名方式
        # 签名步骤四：所有字符转为大写
        $result = strtoupper($sign);
        return $result;
    }

    /**
     * 将xml转为array
     * @param string $xml xml字符串
     * @return array       转换得到的数组
     */
    public function toArray($xml)
    {
        #禁止引用外部xml实体
        libxml_disable_entity_loader(true);
        $result = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        return $result;
    }

    /**
     *
     * 产生随机字符串，不长于32位
     * @param int $length
     * @return 产生的随机字符串
     */
    public function getNonceStr($length = 32)
    {
        $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
        $str = "";
        for ($i = 0; $i < $length; $i++) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
    }

    /**
     * 输出xml字符
     * @throws WxPayException
     **/
    public function toXml($data)
    {
        if (!is_array($data) || count($data) <= 0) {
            throw new WxPayException("数组数据异常！");
        }
        $xml = "<xml>";
        foreach ($data as $key => $val) {
//            if ($key=='mch_id') {
                $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
//            } else {
//                $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
//           }
        }
        $xml .= "</xml>";
        return $xml;
    }


}